home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / nt / emacssrc.zip / EMACSSRC.TAR / emacs-19.17 / lib-src / emacstool.c < prev    next >
C/C++ Source or Header  |  1993-11-16  |  16KB  |  501 lines

  1. /*
  2.  * 
  3.  *    Copyright (C) 1986, 1988, 1990, 1991 Free Software Foundation, Inc.
  4.  * 
  5.  * This file is part of GNU Emacs.
  6.  * 
  7.  * GNU Emacs is distributed in the hope that it will be useful,
  8.  * but without any warranty.  No author or distributor
  9.  * accepts responsibility to anyone for the consequences of using it
  10.  * or for whether it serves any particular purpose or works at all,
  11.  * unless he says so in writing.
  12.  * 
  13.  * Everyone is granted permission to copy, modify and redistribute
  14.  * GNU Emacs, but only under the conditions described in the
  15.  * document "GNU Emacs copying permission notice".   An exact copy
  16.  * of the document is supposed to have been given to you along with
  17.  * GNU Emacs so that you can know how you may redistribute it all.
  18.  * It should be in a file named COPYING.  Among other things, the
  19.  * copyright notice and this notice must be preserved on all copies.
  20.  * 
  21.  *
  22.  * For Emacs in SunView/Sun-Windows: (supported by Sun Unix v3.2 or greater)
  23.  * Insert a notifier filter-function to convert all useful input 
  24.  * to "key" sequences that emacs can understand.  See: Emacstool(1).
  25.  *
  26.  * Author: Jeff Peck, Sun Microsystems, Inc. <peck@eng.sun.com>
  27.  *
  28.  * Original Idea: Ian Batten
  29.  * Updated 15-Mar-88, Jeff Peck: set IN_EMACSTOOL, TERM, TERMCAP
  30.  * Updated 10-Sep-88, Jeff Peck: add XVIEW and JLE support
  31.  * Updated  8-Oct-90, Jeff Peck: add Meta-bit for Xview
  32.  * Updated  6-Mar-91, Jeff Peck: Hack to detect -Wt invocation
  33.  *    [note, TTYSW limitation means you must Click-To-Type in Openwin]
  34.  *    [fixed in OW3 or use local/tty.o]
  35.  *    for better results, this should move to using TERMSW.
  36.  * Updated 10-Mar-91, Jeff Peck, et al: support for TERMSW (TTERM)
  37.  *    allows point-to-type even in OW2
  38.  *
  39.  *     [note: xvetool should be started with the "-nw" flag for emacs!]
  40.  */
  41.  
  42. #ifdef XVIEW
  43. #include <xview/xview.h>
  44. #include <xview/panel.h>
  45. #include <xview/attr.h>
  46. #include <xview/tty.h>
  47. #include <xview/ttysw.h>        /* private defines */
  48. #include <xview/termsw.h>        /* -DTTERM */
  49. #include <xview/font.h>            /* for testing */
  50. #else
  51. #include <suntool/sunview.h>
  52. #include <suntool/tty.h>
  53. #include <suntool/ttysw.h>
  54. #endif XVIEW
  55.  
  56. #ifdef JLE
  57. # include <locale.h>
  58. #endif JLE
  59.  
  60. #include <stdio.h>
  61. #include <sys/file.h>
  62.  
  63. #define BUFFER_SIZE 128               /* Size of all the buffers */
  64.  
  65. /* define WANT_CAPS_LOCK to make f-key T1 (aka F1) behave as CapsLock */
  66. #define WANT_CAPS_LOCK
  67. #ifdef WANT_CAPS_LOCK
  68. int caps_lock;        /* toggle indicator for f-key T1 caps lock */
  69. static char *Caps = "[CAPS] ";        /* Caps Lock prefix string */
  70. #define CAPS_LEN 7            /* strlen (Caps) */
  71. #endif
  72.  
  73. static char *mouse_prefix = "\030\000";    /* C-x C-@ */
  74. static int   m_prefix_length = 2;       /* mouse_prefix length */
  75.  
  76. static char *key_prefix = "\030*";      /* C-x *   */
  77. static int   k_prefix_length = 2;       /* key_prefix length */
  78.  
  79. #ifdef JLE
  80. static char *emacs_name = "nemacs";    /* default run command */
  81. static char *title = "NEmacstool - ";    /* initial title */
  82. #else
  83. static char *emacs_name = "emacs";    /* default run command */
  84. static char *title = "Emacstool - ";    /* initial title */
  85. #endif JLE
  86.  
  87. static char buffer[BUFFER_SIZE];    /* send to ttysw_input */
  88. static char *bold_name = 0;         /* for -bold option */
  89.  
  90. Frame frame;                            /* Base frame for system */
  91.  
  92. #ifndef TTERM
  93. #define SWTYPE TTY
  94. Tty tty_win;                /* Where emacs is reading */
  95. #else
  96. #define SWTYPE TERMSW
  97. Termsw tty_win;                /* Termsw does follow-mouse */
  98. #endif TTERM
  99.  
  100. #ifdef XVIEW
  101. Xv_Window tty_view;            /* Where the events are in Xview*/
  102. #else
  103. Tty tty_view;                /* SunView place filler */
  104. #endif XVIEW
  105.  
  106. int font_width, font_height;            /* For translating pixels to chars */
  107. int left_margin = 0;        /* default window -- frame offset */
  108.  
  109. int console_fd = 0;        /* for debugging: setenv DEBUGEMACSTOOL */
  110. FILE *console;            /* for debugging: setenv DEBUGEMACSTOOL */
  111.  
  112. Icon frame_icon;
  113. /* make an icon_image for the default frame_icon */
  114. static short default_image[258] = 
  115. {
  116. #include <images/terminal.icon>
  117. };
  118. mpr_static(icon_image, 64, 64, 1, default_image);
  119.  
  120. /*
  121.  * Assign a value to a set of keys
  122.  */
  123. int
  124. button_value (event)
  125.      Event *event;
  126. {
  127.   int retval = 0;
  128.   /*
  129.    * Code up the current situation:
  130.    *
  131.    * 1 = MS_LEFT;
  132.    * 2 = MS_MIDDLE;
  133.    * 4 = MS_RIGHT;
  134.    * 8 = SHIFT;
  135.    * 16 = CONTROL;
  136.    * 32 = META;
  137.    * 64 = DOUBLE;
  138.    * 128 = UP;
  139.    */
  140.  
  141.   if (MS_LEFT   == (event_id (event))) retval = 1;
  142.   if (MS_MIDDLE == (event_id (event))) retval = 2;
  143.   if (MS_RIGHT  == (event_id (event))) retval = 4;
  144.  
  145.   if (event_shift_is_down (event)) retval += 8;
  146.   if (event_ctrl_is_down  (event)) retval += 16;
  147.   if (event_meta_is_down  (event)) retval += 32;
  148.   if (event_is_up         (event)) retval += 128;
  149.   return retval;
  150. }
  151.  
  152. /*
  153.  *  Variables to store the time of the previous mouse event that was
  154.  *  sent to emacs.
  155.  *
  156.  *  The theory is that to time double clicks while ignoreing UP buttons,
  157.  *  we must keep track of the accumulated time.
  158.  *
  159.  *  If someone writes a SUN-SET-INPUT-MASK for emacstool,
  160.  *  That could be used to selectively disable UP events, 
  161.  *  and then this cruft wouldn't be necessary.
  162.  */
  163. static long prev_event_sec = 0;
  164. static long prev_event_usec = 0;
  165.  
  166. /*
  167.  *  Give the time difference in milliseconds, where one second
  168.  *  is considered infinite.
  169.  */
  170. int
  171. time_delta (now_sec, now_usec, prev_sec, prev_usec)
  172.      long now_sec, now_usec, prev_sec, prev_usec;
  173. {
  174.   long sec_delta = now_sec - prev_sec;
  175.   long usec_delta = now_usec - prev_usec;
  176.   
  177.   if (usec_delta < 0) {        /* "borrow" a second */
  178.     usec_delta += 1000000;
  179.     --sec_delta;
  180.   }
  181.   
  182.   if (sec_delta >= 10) 
  183.     return (9999);        /* Infinity */
  184.   else
  185.     return ((sec_delta * 1000) + (usec_delta / 1000));
  186. }
  187.  
  188.  
  189. /*
  190.  * Filter function to translate selected input events for emacs
  191.  * Mouse button events become ^X^@(button x-col y-line time-delta) .
  192.  * Function keys: ESC-*{c}{lrt} l,r,t for Left, Right, Top; 
  193.  * {c} encodes the keynumber as a character [a-o]
  194.  */
  195. static Notify_value
  196. input_event_filter_function (window, event, arg, type)
  197. #ifdef XVIEW
  198.      Xv_Window window;
  199. #else
  200.      Window window;
  201. #endif XVIEW
  202.      Event *event;
  203.      Notify_arg arg;
  204.      Notify_event_type type;
  205. {
  206.   struct timeval time_stamp;
  207.  
  208.   if (console_fd) fprintf(console, "Event: %d\n", event_id(event));
  209.  
  210.   /* UP L1 is the STOP key */
  211.   if (event_id(event) == WIN_STOP) {
  212.     ttysw_input(tty_win, "\007\007\007\007\007\007\007", 7);
  213.     return NOTIFY_IGNORED;
  214.   }
  215.  
  216.   /* UP L5 & L7 is Expose & Open, let them pass to sunview */
  217.   if (event_id(event) == KEY_LEFT(5) || event_id(event) == KEY_LEFT(7))
  218.     if(event_is_up (event)) 
  219.       return notify_next_event_func (window, event, arg, type);
  220.     else return NOTIFY_IGNORED;
  221.  
  222.   if (event_is_button (event)) {           /* do Mouse Button events */
  223. /* Commented out so that we send mouse up events too.
  224.    if (event_is_up (event)) 
  225.       return notify_next_event_func (window, event, arg, type);
  226. */
  227.     time_stamp = event_time (event);
  228.     ttysw_input (tty_win, mouse_prefix, m_prefix_length);
  229.     sprintf (buffer, "(%d %d %d %d)\015", 
  230.          button_value (event),
  231.          (event_x (event) - left_margin) / font_width,
  232.          event_y (event) / font_height,
  233.          time_delta (time_stamp.tv_sec, time_stamp.tv_usec,
  234.              prev_event_sec, prev_event_usec)
  235.          );
  236.     ttysw_input (tty_win, buffer, strlen(buffer));
  237.     prev_event_sec = time_stamp.tv_sec;
  238.     prev_event_usec = time_stamp.tv_usec;
  239.     return NOTIFY_IGNORED;
  240.   }
  241.   
  242.   { /* Do the function key events */
  243.     int d;
  244.     char c = (char) 0;
  245.     if ((event_is_key_left  (event)) ?
  246.     ((d = event_id(event) - KEY_LEFT(1)   + 'a'), c='l') : 
  247.     ((event_is_key_right (event)) ?
  248.      ((d = event_id(event) - KEY_RIGHT(1) + 'a'), c='r') : 
  249.      ((event_is_key_top   (event)) ?
  250.       ((d = event_id(event) - KEY_TOP(1)  + 'a'), c='t') : 0)))
  251.       {
  252.     if (event_is_up(event)) return NOTIFY_IGNORED;
  253.     if (event_shift_is_down (event)) c = c -  32;
  254.     /* this will give a non-{lrt} for unshifted keys */
  255.     if (event_ctrl_is_down  (event)) c = c -  64;
  256.     if (event_meta_is_down  (event)) c = c + 128;
  257. #ifdef WANT_CAPS_LOCK
  258. /* set a toggle and relabel window so T1 can act like caps-lock */
  259.     if (event_id(event) == KEY_TOP(1)) 
  260.       {
  261.         /* make a frame label with and without CAPS */
  262.         strcpy (buffer, Caps); 
  263.         title = &buffer[CAPS_LEN];
  264.         strncpy (title, (char *)window_get (frame, FRAME_LABEL),
  265.              BUFFER_SIZE - CAPS_LEN);
  266.         buffer[BUFFER_SIZE] = (char) 0;    
  267.         if (strncmp (title, Caps, CAPS_LEN) == 0)
  268.           title += CAPS_LEN;          /* already Caps */
  269.         caps_lock =  (caps_lock ? 0 : CAPS_LEN);
  270.         window_set(frame, FRAME_LABEL, (title -= caps_lock), 0);
  271.         return NOTIFY_IGNORED;
  272.       }
  273. #endif
  274.     ttysw_input (tty_win, key_prefix, k_prefix_length);
  275.     sprintf (buffer, "%c%c", d, c);
  276.     ttysw_input(tty_win, buffer, strlen(buffer));
  277.  
  278.     return NOTIFY_IGNORED;
  279.       }
  280.   }
  281.   if ((event_is_ascii(event) || event_is_meta(event)) 
  282.       && event_is_up(event)) return NOTIFY_IGNORED;
  283. #ifdef WANT_CAPS_LOCK
  284. /* shift alpha chars to upper case if toggle is set */
  285.   if ((caps_lock) && event_is_ascii(event)
  286.       && (event_id(event) >= 'a') && (event_id(event) <= 'z'))
  287.     event_set_id(event, (event_id(event) - 32));
  288. /* crufty, but it works for now. is there an UPCASE(event)? */
  289. #endif
  290. #ifndef NO_META_BIT
  291. /* under Openwindows/X, the meta bit is not set in the key event,
  292.  * emacs expects this so we add it in here:
  293.  */
  294.   if (event_is_ascii(event) && event_meta_is_down(event))
  295.     event_set_id(event, 128 | event_id(event));
  296. #endif
  297.   return notify_next_event_func (window, event, arg, type);
  298. }
  299.  
  300. main (argc, argv)
  301.      int argc;
  302.      char **argv;
  303. {
  304.   int error_code;    /* Error codes */
  305.   
  306. #ifdef JLE
  307.   setlocale(LC_ALL, "");
  308. #endif JLE
  309.  
  310.   if(getenv("DEBUGEMACSTOOL"))
  311.     console = fdopen (console_fd = open("/dev/console",O_WRONLY), "w");
  312.  
  313.   putenv("IN_EMACSTOOL=t");    /* notify subprocess that it is in emacstool */
  314.  
  315.   if (putenv("TERM=sun") != 0)    /* TTY_WIN will be a TERM=sun window */
  316.     {fprintf (stderr, "%s: Could not set TERM=sun, using `%s'\n",
  317.          argv[0], (char *)getenv("TERM")) ;};
  318.   /*
  319.    * If TERMCAP starts with a slash, it is the pathname of the
  320.    * termcap file, not an entry extracted from it, so KEEP it!
  321.    * Otherwise, it may not relate to the new TERM, so Nuke-It.
  322.    * If there is no TERMCAP environment variable, don't make one.
  323.    */
  324.   {
  325.     char *termcap ;    /* Current TERMCAP value */
  326.     termcap = (char *)getenv("TERMCAP") ;
  327.     if (termcap && (*termcap != '/'))
  328.       {
  329.     if (putenv("TERMCAP=") != 0)
  330.       {fprintf (stderr, "%s: Could not clear TERMCAP\n", argv[0]) ;} ;
  331.       } ;
  332.   } ;
  333.   
  334.   /* find command to run as subprocess in window */
  335.   if (!(argv[0] = (char *)getenv("EMACSTOOL")))    /*  Set emacs command name */
  336.       argv[0] = emacs_name;            
  337.   /* Emacstool recognizes two special args: -rc <file> and -bold <bold-name> */
  338.   for (argc = 1; argv[argc]; argc++)        /* Use last one on line */
  339.     {
  340.       if(!(strcmp ("-rc", argv[argc])))        /* Override if -rc given */
  341.     {int i = argc;
  342.      argv[argc--]=0;        /* kill the -rc argument */
  343.      if (argv[i+1]) {    /* move to argv[0] and squeeze the rest */
  344.        argv[0]=argv[i+1];
  345.        for (; argv[i+2]; (argv[i]=argv[i+2],argv[++i]=0));
  346.      }
  347.        }
  348.  
  349.       if (!(strcmp ("-bold", argv[argc]))) 
  350.       {int i = argc;
  351.        argv[argc--]=0;        /* kill the -bold argument */
  352.        if (argv[i+1]) {    /* move to bold_name and squeeze the rest */
  353.            bold_name = argv[i+1];
  354.            for (; argv[i+2]; (argv[i]=argv[i+2],argv[++i]=0));
  355.        }
  356.        }
  357.   };
  358.  
  359.   strcpy (buffer, title);
  360.   strncat (buffer, argv[0],         /* append run command name */
  361.        (BUFFER_SIZE - (strlen (buffer)) - (strlen (argv[0]))) - 1);
  362.  
  363.   error_code = interpose_on_window(argc,argv);
  364.   if (error_code != 0) {        /* Barf */
  365.       fprintf (stderr, "notify_interpose_event_func returns %d.\n", error_code);
  366.       exit (1);
  367.   }
  368.  
  369. #ifdef XVIEW
  370.   xv_main_loop (frame);                  /* And away we go */
  371. #else
  372.   window_main_loop (frame);
  373. #endif XVIEW
  374. }
  375.  
  376. #ifdef XVIEW
  377. int interpose_on_window(argc,argv)
  378.     int argc;
  379.     char **argv;
  380. {
  381. #ifndef TTERM
  382.     int i, font_width_adjust = 1; /* hackery, and hueristics */
  383.     /* if -Wt is not supplied, then font comes out as lucida-14 (width=8)
  384.      * rather than the screen.r.12 (width=7) typically used
  385.      * this hack attempts to workaround it.
  386.      * could use a env var EMACSTOOL_DEFAULT_FONT_WIDTH instead */
  387.     for (i = 1; argv[i]; i++) {
  388.     if (!(strcmp ("-Wt", argv[i])))
  389.         {font_width_adjust = 0;
  390.          if (console_fd) fprintf(console, "-Wt = %d\n", font_width_adjust);
  391.          break;}
  392.     }
  393. #endif TTERM
  394.     /* initialize Xview, and strip window args */
  395.     xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, 0);
  396.  
  397.     /* do this first, so arglist can override it */
  398.     frame_icon = icon_create (ICON_LABEL, "Emacstool",
  399.                   ICON_IMAGE, &icon_image,
  400.                   0);
  401.  
  402.     /* Build a frame to run in */
  403.     frame = xv_create ((Xv_Window)NULL, FRAME,
  404.                FRAME_LABEL, buffer,
  405.                FRAME_ICON, frame_icon,
  406.                0);
  407.  
  408.     /* Create a tty with emacs in it */
  409.     tty_win = xv_create (frame, SWTYPE, WIN_IS_CLIENT_PANE,
  410.              TTY_QUIT_ON_CHILD_DEATH, TRUE, 
  411.              TTY_BOLDSTYLE, TTYSW_BOLD_INVERT,
  412.              TTY_ARGV, argv, 
  413.              0);
  414.  
  415.     if (bold_name) {
  416.     (void)xv_set(tty_win, TTY_BOLDSTYLE_NAME, bold_name, 0);
  417.     }
  418.  
  419.     {
  420.     Xv_font font;        /* declare temp font variable */
  421.     font = (Xv_font)xv_get (tty_win, XV_FONT);
  422.     font_height = (int)xv_get (font, FONT_DEFAULT_CHAR_HEIGHT);
  423.     font_width  = (int)xv_get (font, FONT_DEFAULT_CHAR_WIDTH);
  424.     }
  425.     if (console_fd) fprintf(console, "Width = %d\n", font_width);
  426.  
  427. #ifndef TTERM
  428.     font_width -= font_width_adjust; /* A guess! font bug in ttysw*/
  429. #else
  430.     /* make the termsw act as a tty */
  431.     xv_set(tty_win, TERMSW_MODE, TTYSW_MODE_TYPE, 0);
  432.     /* termsw has variable offset depending on scrollbar size/location */
  433.     left_margin = (int)xv_get (tty_win, TEXTSW_LEFT_MARGIN);
  434. #endif TTERM
  435.  
  436.     tty_view = (Xv_Window) xv_get (tty_win, OPENWIN_NTH_VIEW, 0);
  437.     xv_set(tty_view,
  438.        WIN_CONSUME_EVENTS, 
  439.        WIN_MOUSE_BUTTONS, WIN_UP_EVENTS,
  440.        ACTION_ADJUST, ACTION_MENU,
  441.        WIN_ASCII_EVENTS, 
  442.        WIN_LEFT_KEYS, WIN_TOP_KEYS, WIN_RIGHT_KEYS,
  443.        0,
  444.        0);
  445.     /* Interpose my event function */
  446.     return (int) notify_interpose_event_func 
  447.     (tty_view, input_event_filter_function, NOTIFY_SAFE);
  448. }
  449. #else
  450. int interpose_on_window (argc, argv)
  451.  int argc;
  452.  char **argv;
  453. {
  454.     /* do this first, so arglist can override it */
  455.     frame_icon = icon_create (ICON_LABEL, "Emacstool",
  456.                   ICON_IMAGE, &icon_image,
  457.                   0);
  458.  
  459.     /* Build a frame to run in */
  460.     frame = window_create ((Window)NULL, FRAME,
  461.                FRAME_LABEL, buffer,
  462.                FRAME_ICON, frame_icon,
  463.                FRAME_ARGC_PTR_ARGV, &argc, argv,
  464.                0);
  465.  
  466.     /* Create a tty with emacs in it */
  467.     tty_win = window_create (frame, TTY, 
  468.                  TTY_QUIT_ON_CHILD_DEATH, TRUE, 
  469.                  TTY_BOLDSTYLE, TTYSW_BOLD_INVERT,
  470.                  TTY_ARGV, argv, 
  471.                  0);
  472.  
  473.     if (bold_name) {
  474.     (void)window_set(tty_win, TTY_BOLDSTYLE_NAME, bold_name, 0);
  475.     }
  476.  
  477.     /* ttysw uses pf_default, one must set WIN_FONT explicitly */
  478.                        window_set (tty_win, WIN_FONT, pf_default(), 0);
  479.     font_height = (int)window_get (tty_win, WIN_ROW_HEIGHT);
  480.     font_width  = (int)window_get (tty_win, WIN_COLUMN_WIDTH);
  481.  
  482.     tty_view = tty_win;
  483.     window_set(tty_view,
  484.            WIN_CONSUME_PICK_EVENTS, 
  485.            WIN_STOP,
  486.            WIN_MOUSE_BUTTONS, WIN_UP_EVENTS,
  487.            /* LOC_WINENTER, LOC_WINEXIT, LOC_MOVE, */
  488.            0,
  489.            WIN_CONSUME_KBD_EVENTS, 
  490.            WIN_STOP,
  491.            WIN_ASCII_EVENTS, 
  492.            WIN_LEFT_KEYS, WIN_TOP_KEYS, WIN_RIGHT_KEYS,
  493.            /* WIN_UP_ASCII_EVENTS, */
  494.            0,
  495.            0);
  496.     /* Interpose my event function */
  497.     return (int) notify_interpose_event_func 
  498.     (tty_view, input_event_filter_function, NOTIFY_SAFE);
  499. }
  500. #endif XVIEW
  501.